package com.ylz.sjzx.sio.sdk.client.core.ws;

import com.ylz.sjzx.sio.common.core.constant.IMConstant;
import com.ylz.sjzx.sio.common.core.core.SioBase;
import com.ylz.sjzx.sio.common.core.enums.Cmd;
import com.ylz.sjzx.sio.common.core.exception.LoginException;
import com.ylz.sjzx.sio.sdk.client.core.IMNioBase;
import com.ylz.sjzx.sio.sdk.client.core.SocketProcess;
import com.ylz.sjzx.sio.sdk.client.session.IMSession;
import com.ylz.sjzx.sio.sdk.client.utils.SessionUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.AttributeKey;
import lombok.extern.slf4j.Slf4j;

/**
 * @author wiqi
 * @version 1.0
 * @date 2020/12/8
 */
@Slf4j
public class FinalChannelEventHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    /**
     * 聊天室初始化连接
     *
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        IMNioBase.clean();
        SioBase.clean();
        if (msg != null && msg instanceof FullHttpRequest) {
            //登录操作
            FullHttpRequest request = (FullHttpRequest) msg;
            String uri = request.getUri();
            if (null != uri && uri.contains(IMConstant.DEFAULT_WEB_SOCKET_LINK) && uri.contains("?")) {
                String[] uriArray = uri.split("\\?");
                if (null == uriArray || uriArray.length != 2) {
                    throw new LoginException("请求uri 异常:" + uri);
                }

                //session 解析
                IMSession imSession = SessionUtil
                        .parse2Session(IMNioBase.getGlobalChannel().get(ctx.channel().id().asShortText()), uriArray[1]);

                IMNioBase.setSession(imSession);
                //login 直接处理
                SioBase.getInnerAdapterMap().get(Cmd.login.getValue()).process();
                request.setUri(uriArray[0]);
            }
        }
        super.channelRead(ctx, msg);

    }

    /**
     * 业务处理
     *
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) {
        //业务处理
        SocketProcess.channelRead0(ctx, msg);
    }

    /**
     * 退出登录
     *
     * @param ctx
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        //清除登录信息
        SessionUtil.getIMSessionService().logout(ctx.channel().id().asShortText());
        IMNioBase.getGlobalChannel().remove(ctx.channel().id().asShortText());
    }

    //初始绑定
    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        IMNioBase.getGlobalChannel().put(ctx.channel().id().asShortText(), ctx.channel());
    }

    /**
     * 心跳过期处理
     *
     * @param ctx
     * @param evt
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
        if (!(evt instanceof IdleStateEvent)) {
            return;
        }
        IdleStateEvent idleEvent = (IdleStateEvent) evt;

        if (idleEvent.state().equals(IdleState.WRITER_IDLE)) {
            ctx.channel().attr(AttributeKey.valueOf(IMConstant.HEARTBEAT_KEY)).set(System.currentTimeMillis());
            ctx.channel().writeAndFlush(new TextWebSocketFrame("3"));
        }
        //如果心跳请求发出30秒内没收到响应，则关闭连接
        if (idleEvent.state().equals(IdleState.READER_IDLE)) {

            Long lastTime = (Long) ctx.channel().attr(AttributeKey.valueOf(IMConstant.HEARTBEAT_KEY)).get();
            if (lastTime != null && System.currentTimeMillis() - lastTime >= IMNioBase.PONG_TIME_OUT) {
                ctx.channel().close();
            }
            ctx.channel().attr(AttributeKey.valueOf(IMConstant.HEARTBEAT_KEY)).set(null);
        }

    }
}
